#!/usr/bin/env php
<?php
/**************************************************************************
 *
 *   Copyright 2010 American Public Media Group
 *
 *   This file is part of AIR2.
 *
 *   AIR2 is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   AIR2 is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with AIR2.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************/

require_once 'app/init.php';
require_once APPPATH.'../tests/Test.php';
require_once APPPATH.'../tests/AirHttpTest.php';
require_once APPPATH.'../tests/AirTestUtils.php';
require_once APPPATH.'../tests/models/TestUser.php';
require_once APPPATH.'../tests/models/TestSource.php';
require_once APPPATH.'../tests/models/TestOrganization.php';

define('MY_TEST_PASS', 'fooBar123.');

plan(34);

AIR2_DBManager::init();

// Create 4 users in 3 different orgs.
$users = array();
$count = 0;
while ($count++ < 4) {
    $u = new TestUser();
    $u->user_password = MY_TEST_PASS;
    $u->save();
    $users[] = $u;
}

// test Orgs
$orgs = array();
$count = 0;
while ($count++ < 3) {
    $o = new TestOrganization();
    $o->save();
    $orgs[] = $o;
}

$orgs[0]->add_users(array($users[0]));
$orgs[0]->save();
$orgs[1]->add_users(array($users[2]), 4);  // MANAGER
$orgs[1]->save();
$orgs[2]->add_users(array($users[3]));
$orgs[2]->add_users(array($users[1]), 3);  // WRITER
$orgs[2]->save();

// can't use TestProject because we need to set shared_flag = 0
// clean up any old data
$q = AIR2_Query::create();
$q->delete('Project p');
$q->where('p.prj_uuid = ?', 'testproj1234');
$q->execute();
$q = AIR2_Query::create();
$q->delete('Project p');
$q->where('p.prj_uuid = ?', 'testproj4567');
$q->execute();
$q = AIR2_Query::create();
$q->delete('Inquiry i');
$q->where('i.inq_uuid = ?', 'testinq12345');
$q->execute();
// question should have cascaded from inquiry delete above,
// but you never know.
$q = AIR2_Query::create();
$q->delete('Question q');
$q->where('q.ques_uuid = ?', 'testquestion');
$q->execute();

$source = new TestSource();
$source->add_orgs(array($orgs[1], $orgs[2]));
$source->save();

$project = new Project();
$project->prj_shared_flag = 0;
$project->prj_uuid = 'testproj1234';
$project->prj_name = 'authz-unit-test-test123';
$project->prj_display_name = 'test project 123';
$project->add_orgs( array( $orgs[1], $orgs[2] ) );
$project->save();
$sharedproject = new Project();
$sharedproject->prj_shared_flag = 1;
$sharedproject->prj_uuid = 'testproj4567';
$sharedproject->prj_name = 'authz-unit-test-test456';
$sharedproject->prj_display_name = 'test project 456';
$sharedproject->add_orgs( array( $orgs[1], $orgs[2] ) );
$sharedproject->save();
$inquiry = new Inquiry();
$inquiry->inq_public_flag = 0;
$inquiry->inq_uuid  = 'testinq12345';
$inquiry->inq_title = 'authz-unit-test-test123';
$inquiry->inq_ext_title = 'test inquiry 123';
$inquiry->add_projects(array($project, $sharedproject));
$inquiry->save();
$ques = new Question();
$ques->ques_inq_id = $inquiry->inq_id;
$ques->ques_dis_seq = 1;
$ques->ques_value = 'what is the air-speed velocity of a swallow?';
$ques->ques_uuid = 'testquestion';
$ques->save();
$srs = new SrcResponseSet();
$srs->srs_src_id = $source->src_id;
$srs->srs_date = air2_date();
$srs->srs_inq_id = $inquiry->inq_id;
$srs->save();
$sr = new SrcResponse();
$sr->sr_src_id = $source->src_id;
$sr->sr_srs_id = $srs->srs_id;
$sr->sr_ques_id = $ques->ques_id;
$sr->sr_orig_value = 'european or african swallow?';
$sr->save();


// actual tests
is( $srs->user_may_write( $users[0] ), AIR2_AUTHZ_IS_DENIED,
    "user cannot create new SrcResponseSet for Org to which they do not belong");
is( $srs->user_may_write( $users[2] ), AIR2_AUTHZ_IS_ORG,
    "user may create new SrcResponseSet for Org in which they are a WRITER");
is( $srs->user_may_write( $users[3] ), AIR2_AUTHZ_IS_DENIED,
    "user may not create new SrcResponseSet if they are not a WRITER in the assigned Org");
is( $srs->user_may_manage( $users[1] ), AIR2_AUTHZ_IS_DENIED,
    "user who is contact for a Project may not manage SrcResponseSet unless they have MANAGER role for a related Org");
is( $srs->user_may_manage( $users[2] ), AIR2_AUTHZ_IS_MANAGER,
    "user who is contact for a Project may not manage SrcResponseSet unless they have MANAGER role for a related Org");
is( $srs->user_may_manage( $users[3] ), AIR2_AUTHZ_IS_DENIED,
    "users[3] may not manage SrcResponseSet where they cannot even write");

// srs annotations
$anno = new SrsAnnotation();
$anno->srsan_srs_id   = $srs->srs_id;
is( $anno->user_may_read( $users[0] ), AIR2_AUTHZ_IS_DENIED,
    "user may not read annotation where they cannot read SrcResponseSet");
is( $anno->user_may_write( $users[0] ), AIR2_AUTHZ_IS_DENIED,
    "user may not write new annotation where they cannot write SrcResponseSet");
is( $anno->user_may_write( $users[1] ), AIR2_AUTHZ_IS_ORG,
    "user may read annotation where they can read SrcResponseSet");
is( $anno->user_may_write( $users[2] ), AIR2_AUTHZ_IS_ORG,
    "user may write new annotation where they can write SrcResponseSet");

// srs saved annotations
$anno->srsan_cre_user = $users[1]->user_id;
$anno->save();
is( $anno->user_may_write( $users[2] ), AIR2_AUTHZ_IS_DENIED,
    "user may not write existing annotation if they don't own it");
is( $anno->user_may_write( $users[1] ), AIR2_AUTHZ_IS_OWNER,
    "user may write existing annotation if they own it");

// sr annotations
$anno2 = new SrAnnotation();
$anno2->sran_sr_id   = $sr->sr_id;
is( $anno2->user_may_read( $users[0] ), AIR2_AUTHZ_IS_DENIED,
    "user may not read annotation where they cannot read SrcResponse");
is( $anno2->user_may_write( $users[0] ), AIR2_AUTHZ_IS_DENIED,
    "user may not write new annotation where they cannot write SrcResponse");
is( $anno2->user_may_write( $users[1] ), AIR2_AUTHZ_IS_ORG,
    "user may read annotation where they can read SrcResponse");
is( $anno2->user_may_write( $users[2] ), AIR2_AUTHZ_IS_ORG,
    "user may write new annotation where they can write SrcResponse");

// sr saved annotations
$anno2->sran_cre_user = $users[1]->user_id;
$anno2->save();
is( $anno2->user_may_write( $users[2] ), AIR2_AUTHZ_IS_DENIED,
    "user may not write existing annotation if they don't own it");
is( $anno2->user_may_write( $users[1] ), AIR2_AUTHZ_IS_OWNER,
    "user may write existing annotation if they own it");


// some baselines
$q = AIR2_Query::create();
$q->from('Project p');
$q->where('prj_shared_flag = 1');
$shared_projects = $q->count();
//diag("baseline $shared_projects shared_projects");
$projs = $q->execute();
foreach ($projs as $proj) {
    //diag_dump( $proj->getData() );
}
$q = AIR2_Query::create();
$q->from('Project p');
$q->where('prj_shared_flag = 0');
$unshared_projects = $q->count();
//diag("baseline $unshared_projects unshared_projects");
$projs = $q->execute();
foreach ($projs as $proj) {
    //diag_dump( $proj->getData() );
}


// query authz
$q = AIR2_Query::create();
$q->from('SrcResponseSet srs');
SrcResponseSet::query_may_read($q, $users[0]);
is( $q->count(), 0, "users[0] may not read (shares no Orgs with any Source related to SrcResponseSet)");

$q = AIR2_Query::create();
$q->from('SrcResponseSet srs');
SrcResponseSet::query_may_read($q, $users[2]);
is( $q->count(), 1, "users[2] may read SrcResponseSet");

$q = AIR2_Query::create();
$q->from('SrcResponseSet srs');
SrcResponseSet::query_may_read($q, $users[3]);
is( $q->count(), 1, "users[3] may read SrcResponseSet");

$q = AIR2_Query::create();
$q->from('Source src');
Source::query_may_write($q, $users[2]);
is( $q->count(), 1, "users[2] may write to Source (has MANAGER role)");

$q = AIR2_Query::create();
$q->from('Inquiry inq');
Inquiry::query_may_write($q, $users[2]);
is( $q->count(), 1, "users[2] may write to Inquiry (is owner in both related Projects)");

$q = AIR2_Query::create();
$q->from('Project prj');
Project::query_may_write($q, $users[2]);
$projs = $q->execute();
$writeable_projs = array();
foreach ($projs as $proj) {
/*
    diag_dump( $proj->getData() );
    foreach ($proj->ProjectInquiry as $pinq) {
        diag_dump( $pinq->getData() );
    }
    foreach ($proj->ProjectOrg as $porg) {
        diag_dump( $porg->getData() );
    }
*/
    $writeable_projs[] = $proj->prj_uuid;
}
//diag($q->getSqlQuery());
is( $q->count(), 2, "users[2] may write to Projects (is owner in both related Projects)");
ok( in_array('testproj4567', $writeable_projs), "'testproj4567' is writeable Project");
ok( in_array('testproj1234', $writeable_projs), "'testproj1234' is writeable Project");

$q = AIR2_Query::create();
$q->from('SrcResponseSet srs');
SrcResponseSet::query_may_write($q, $users[2]);
//diag($q->getSqlQuery());
is( $q->count(), 1, "users[2] may write to SrcResponseSet (has MANAGER role)");

$q = AIR2_Query::create();
$q->from('SrcResponseSet srs');
SrcResponseSet::query_may_write($q, $users[1]);
//diag($q->getSqlQuery());
is( $q->count(), 1, "users[1] may write to SrcResponseSet (has WRITER role)");

$q = AIR2_Query::create();
$q->from('SrcResponseSet srs');
SrcResponseSet::query_may_write($q, $users[3]);
//diag($q->getSqlQuery());
is( $q->count(), 0, "users[3] may not write to SrcResponseSet (shared Project != write perm)"); // TODO rules are not clear on this

$q = AIR2_Query::create();
$q->from('Source src');
Source::query_may_manage($q, $users[2]);
//diag($q->getSqlQuery());
is( $q->count(), 1, "users[2] may manage Source where they are primary contact on parent Project");

$q = AIR2_Query::create();
$q->from('Inquiry inq');
Inquiry::query_may_manage($q, $users[2]);
//diag($q->getSqlQuery());
is( $q->count(), 1, "users[2] may manage Inquiry where they are primary contact on parent Project");

$q = AIR2_Query::create();
$q->from('Project prj');
Project::query_may_manage($q, $users[2]);
//diag($q->getSqlQuery());
is( $q->count(), 2, "users[2] may manage Projects where they own");

$q = AIR2_Query::create();
$q->from('SrcResponseSet srs');
SrcResponseSet::query_may_manage($q, $users[2]);
//diag($q->getSqlQuery());
is( $q->count(), 1, "users[2] may manage SrcResponseSet where they are primary contact on parent Project");

$q = AIR2_Query::create();
$q->from('SrcResponseSet srs');
SrcResponseSet::query_may_manage($q, $users[3]);
//diag($q->getSqlQuery());
is( $q->count(), 0, "users[3] may not manage SrcResponseSet");

// clean up
$sharedproject->delete();
$project->delete();
$inquiry->delete();
